<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
      *{
        padding: 0;
        margin: 0;
      }
      #canvas {
        border: 2px dotted #ccc;
      }
    </style>
</head>
<body>
    <div class="con-box">
      <canvas id="canvas" width="600px" height="400px"></canvas>
      <input type="range" class="range" min="1" max="30" value="1" id="range">
      <button id="revoke">撤销</button>
      <button id="save-btn">保存</button>
      <button id="file">转化为file</button>
      <button id="reset" >重置</button>
    </div>
</body>
<script>
// 获取canvas元素的DOM对象 
const canvas=document.getElementById('canvas')
// 获取设置画笔粗细的dom元素
let range = document.querySelector("#range");
let revoke=document.querySelector("#revoke");
let reset=document.querySelector("#reset");
let saveBtn=document.querySelector("#save-btn");
let fileBtn=document.querySelector("#file");


// 获取渲染上下文和它的绘画功能
const ctx= canvas.getContext('2d')
// 笔画内容的颜色，一般为黑色
ctx.strokeStyle='#000'

let historyArr = [] //保存所有的操作
let currentPath = null;

// 注册鼠标按下事件
canvas.addEventListener('mousedown',mousedownFun)

// 按下事件
function mousedownFun(e){
  console.log('按下',e.pageX,e.pageY)
  // 开始本次绘画(与画笔大小设置有关)
  ctx.beginPath();
  // 设置画笔的粗细
  ctx.lineWidth = range.value || 1
  // 获取按下的那一刻鼠标的坐标,同时移动画笔
  ctx.moveTo(e.pageX,e.pageY)

  // 记录当前笔画起始点的特征(颜色 粗细 位置)
  currentPath = {
    color: ctx.strokeStyle,
    width: ctx.lineWidth,
    points: [{ x: e.offsetX, y: e.offsetY }]
  }

  // 注册移动事件
  canvas.addEventListener('mousemove',mousemoveFun)
  // 注册抬起事件
  canvas.addEventListener('mouseup',mouseupFun)
}

// 移动事件
function mousemoveFun(e){
  console.log('移动')
  // 使用直线连接路径的终点 x，y 坐标的方法（并不会真正地绘制）
  ctx.lineTo(e.pageX,e.pageY)
  // 记录画笔的移动的每一个坐标位置
  currentPath.points.push({ x: e.offsetX, y: e.offsetY });
  // 使用 stroke() 方法真正地画线
  ctx.stroke()
}

// 抬起事件
function mouseupFun(e){
  // 一笔结束后存储起来
  historyArr.push(currentPath);
  console.log('historyArr',historyArr)
  // 结束本次绘画(与画笔大小设置有关)
  ctx.closePath();
  console.log('抬起')
  // 移除移动事件
  canvas.removeEventListener('mousemove', mousemoveFun)
  // 移除抬起事件
  canvas.removeEventListener('mouseup', mouseupFun)
}

// 鼠标移出canvas所在的区域事件-处理鼠标移出canvas所在区域后，然后移入不按下鼠标也可以绘制笔画
canvas.addEventListener('mouseout',e=>{
  // 移除移动事件
  canvas.removeEventListener('mousemove', mousemoveFun)
})


  // 撤销按钮点击事件
revoke.addEventListener('click', e => {
  if (historyArr.length === 0) return;
  // 删除最后一条的记录
  historyArr.pop()
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawPaths(historyArr);
});

// 重置整个画布
reset.addEventListener('click',e=>{
  //清空整个画布
  ctx.clearRect(0, 0, canvas.width, canvas.height);
})

// 保存为图片
saveBtn.addEventListener('click',()=>{
  let imgURL = canvas.toDataURL({format: "image/png", quality:1, width:600, height:400});
  console.log('imgURL',imgURL)
  let link = document.createElement('a');
  link.download = "tupian";
  link.href = imgURL;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
})

// 画所有的路径
function drawPaths(paths) {
  console.log(11,paths)
  paths.forEach(path => {
    ctx.beginPath();
    ctx.strokeStyle = path.color;
    ctx.lineWidth = path.width;
    ctx.moveTo(path.points[0].x, path.points[0].y);
    // path.points.slice(1) 少画 与  path.points 区别是少画一笔和正常笔数
    console.log('path',path)
    path.points.slice(1).forEach(point => {
      ctx.lineTo(point.x, point.y);
    });
    ctx.stroke();
  });
}

// base64转化为file文件
function base64changeFile (urlData, fileName) {
  // split将按照','字符串按照,分割成一个数组，
  // 这个数组通常包含了数据类型（MIME type）和实际的数据。
  // 数组的第1项是类型 第2项是数据
  const arr = urlData.split(',')
  // data:image/png;base64
  const mimeType = arr[0].match(/:(.*?);/)[1]
  console.log('类型',mimeType)
  // 将base64编码的数据转换为普通字符串
  const bytes = atob(arr[1])
  let n = bytes.length
  // 创建了一个新的Uint8Array对象，并将这些字节复制到这个对象中。
  const fileFormat = new Uint8Array(n)
  while (n--) {
    fileFormat[n] = bytes.charCodeAt(n)
  }
  return new File([fileFormat], fileName, { type: mimeType })
}

fileBtn.addEventListener('click',()=>{
  let imgURL = canvas.toDataURL({format: "image/png", quality:1, width:600, height:400});
  let file = base64changeFile(imgURL,'qianMing')
  console.log('file',file)
})
</script>
</html>

